# jsb/plugs/gozer/lists.py
#
#
#

""" lists per global/channel/user """

## jsb imports

from jsb.utils.exception import handle_exception
from jsb.lib.commands import cmnds
from jsb.lib.examples import examples
from jsb.lib.users import users
from jsb.lib.config import getmainconfig

## sqlalchemy imports

from jsb.database.alchemy import Base, create_session, trans, transfunc, create_all, query
from datetime import datetime, timedelta
from time import localtime
from sqlalchemy import Column, String, Integer, Text, DateTime, ForeignKey, Sequence
import sqlalchemy as sa

## Lists model

class Lists(Base):
    __tablename__ = 'list'
    __table_args__ = {'useexisting': True}
    indx = Column('indx', Integer, primary_key=True)
    username = Column('username', String(255), nullable=False)
    listname = Column('listname', String(255), nullable=False)
    item = Column('item', Text, nullable=False)

    def __init__(self, username, listname, item):
        self.username = username
        self.listname = listname
        self.item = item

## init

create_all('lists')

## plugin size function

def size():
    """ return number of lists """
    count = query(sa.func.count(Lists.indx)).count()
    return count 

## getlists function

def getlists(username):
    """ get all lists of user """
    lists = query(Lists).filter(Lists.username==username)
    if lists:
        return lists

## getlist function

def getlist(username, listname):
    """ get list of user """
    lists = query(Lists).filter(Lists.username==username).filter(Lists.listname==listname)
    if lists:
        return lists

## addtolist function

@transfunc
def addtolist(session, username, listname, item):
    """ add item to list """
    list = Lists(username, listname, item)
    session.add(list)
    session.commit()
    return list.indx

## delfromlist function

@transfunc
def delfromlist(session, username, indx):
    """ delete item from list """
    item = session.query(Lists).filter(Lists.username==username).filter(Lists.indx==indx).first()
    if item:
        session.delete(item)
        return 1

## mergelist function

def mergelist(username, listname, l):
    """ merge 2 lists """
    teller = 0
    for i in l: addtolist(username, listname, i) ; teller += 1
    return teller

## list-global command

def handle_listsglobal(bot, ievent):
    """ lists <listname> [',' <item>] .. global lists"""
    if not ievent.rest: ievent.missing("<listname> [',' <item>]") ; return
    try: listname, item = ievent.rest.split(',', 1)
    except ValueError:
        l = getlist('all', ievent.rest)
        if not l: ievent.reply('no %s list available' % ievent.rest) ; return
        result = []
        for i in l: result.append("%s) %s" % (i.indx, i.item))
        ievent.reply("%s global list: " % ievent.rest, result)
        return
    listname = listname.strip().lower()
    item = item.strip()
    if not listname or not item: ievent.missing("<listname> [',' <item>]") ; return
    result = 0
    try: result = addtolist('all', listname, item)
    except Exception, ex:
        handle_exception()
        ievent.reply('ERROR: %s' % str(ex))
        return
    if result: ievent.reply('%s (%s) added to %s list' % (item, result, listname))
    else: ievent.reply('add failed')

cmnds.add('lists-global', handle_listsglobal, 'USER')
examples.add('lists-global', "lists-global <listname> [',' <item>] .. show content of list or add item to list", '1) lists-global bla 2) lists-global bla, mekker')

def handle_listsglobaldel(bot, ievent):
    """ list-globaldel <listname> ',' <listofnrs> .. remove items with indexnr from list """
    if not ievent.rest: ievent.missing('<listofnrs>') ; return
    try:
        nrs = []
        for i in ievent.rest.split(): nrs.append(int(i))
    except ValueError:
        ievent.reply('%s is not an integer' % i)
        return
    nrs.sort()
    failed = []
    itemsdeleted = 0
    try:
        for i in nrs:
            result = delfromlist('all', i)
            if not result: failed.append(str(i))
            else: itemsdeleted += 1
    except Exception, ex:
        handle_exception()
        ievent.reply('ERROR: %s' % str(ex))
        return
    if failed: ievent.reply('failed to delete %s' % ' '.join(failed))
    ievent.reply('%s item(s) removed' % itemsdeleted)

cmnds.add('lists-globaldel', handle_listsglobaldel, 'USER')
examples.add('lists-globaldel', "lists-globaldel <listname> ', ' <listofnrs> .. remove items with indexnr from list", '1) lists-globaldel 1 2) lists-globaldel 0 3 6')

def handle_listsglobalshow(bot, ievent):
    """ show avaiable global lists """
    l = getlists('all')
    if not l: ievent.reply('no lists available') ; return
    else:
        result = []
        for i in l:
            if not i.listname in result: result.append(i.listname)
        ievent.reply("global lists: " , result)

cmnds.add('lists-globalshow', handle_listsglobalshow, 'USER')
examples.add('lists-globalshow', 'show available global lists' , 'lists-globalshow')

def handle_listschan(bot, ievent):
    """ lists-chan <listname> [',' <item>] .. global lists"""
    if not ievent.rest: ievent.missing("<listname> [',' <item>]") ; return
    try: listname, item = ievent.rest.split(',', 1)
    except ValueError:
        l = getlist(ievent.channel, ievent.rest)
        if not l: ievent.reply('no %s list available' % ievent.rest) ; return
        result = []
        for i in l: result.append("%s) %s" % (i.indx, i.item))
        ievent.reply("%s list for %s: " % (ievent.rest, ievent.channel), result)
        return
    listname = listname.strip().lower()
    item = item.strip()
    if not listname or not item: ievent.missing("<listname> [',' <item>]") ; return
    result = 0
    try: result = addtolist(ievent.channel, listname, item)
    except Exception, ex:
        handle_exception()
        ievent.reply('ERROR: %s' % str(ex))
        return
    if result: ievent.reply('%s (%s) added to %s list' % (item, result, listname))
    else: ievent.reply('add failed')

cmnds.add('lists-chan', handle_listschan, 'USER')
examples.add('lists-chan', "lists-chan <listname> [',' <item>] .. show content of list or add item to list", '1) lists-chan bla 2) lists-chan bla, mekker')

def handle_listschandel(bot, ievent):
    """ lists-chandel <listname> ',' <listofnrs> .. remove items with indexnr from list """
    if not ievent.rest: ievent.missing('<listofnrs>') ; return
    try:
        nrs = []
        for i in ievent.rest.split(): nrs.append(int(i))
    except ValueError: ievent.reply('%s is not an integer' % i) ; return
    nrs.sort()
    failed = []
    itemsdeleted = 0
    try:
        for i in nrs:
            result = delfromlist(ievent.channel, i)
            if not result: failed.append(str(i))
            else: itemsdeleted += 1
    except Exception, ex:
        handle_exception()
        ievent.reply('ERROR: %s' % str(ex))
        return
    if failed: ievent.reply('failed to remove %s' % ' '.join(failed))
    ievent.reply('%s item(s) removed' % itemsdeleted)

cmnds.add('lists-chandel', handle_listschandel, 'USER')
examples.add('lists-chandel', "lists-chandel <listname> ',' <listofnrs> .. remove items with indexnr from list", '1) lists-chandel 1 2) lists-chandel 0 3 6')

def handle_listschanshow(bot, ievent):
    """ show avaiable lists """
    l = getlists(ievent.channel)
    if not l: ievent.reply('no lists available') ; return
    else:
        result = []
        for i in l:
            if not i.listname in result: result.append(i.listname)
        ievent.reply("lists for %s: " % ievent.channel, result)

cmnds.add('lists-chanshow', handle_listschanshow, 'USER')
examples.add('lists-chanshow', 'show available channel lists' , 'lists-chanshow')

def handle_lists(bot, ievent):
    """ lists <listname> [',' <item>] .. global lists"""
    if not ievent.rest: ievent.missing("<listname> [',' <item>]") ; return
    username = users.getname(ievent.userhost)
    try: listname, item = ievent.rest.split(',', 1)
    except ValueError:
        l = getlist(username, ievent.rest)
        if not l: ievent.reply('no %s list available' % ievent.rest) ; return
        result = []
        for i in l: result.append("%s) %s" % (i.indx, i.item))
        ievent.reply("%s list for %s: " % (ievent.rest, username), result)
        return
    listname = listname.strip().lower()
    item = item.strip()
    if not listname or not item: ievent.missing("<listname> [',' <item>]") ; return
    result = 0
    try: result = addtolist(username, listname, item)
    except Exception, ex:
        handle_exception()
        ievent.reply('ERROR: %s' % str(ex))
        return
    if result: ievent.reply('%s (%s) added to %s list' % (item, result, listname))
    else: ievent.reply('add failed')

cmnds.add('lists', handle_lists, 'USER')
examples.add('lists', "lists <listname> [',' <item>] .. show content of list or add item to list", '1) lists bla 2) lists bla, mekker')

def handle_listsdel(bot, ievent):
    """ lists-del <listname> ',' <listofnrs> .. remove items with indexnr from list """
    if not ievent.rest: ievent.missing('<listofnrs>') ; return
    try:
        nrs = []
        for i in ievent.rest.split(): nrs.append(int(i))
    except ValueError: ievent.reply('%s is not an integer' % i) ; return
    username = users.getname(ievent.userhost)
    nrs.sort()
    failed = []
    itemsdeleted = 0
    try:
        for i in nrs:
            result = delfromlist(username, i)
            if not result: failed.append(str(i))
            else: itemsdeleted += 1
    except Exception, ex:
        handle_exception()
        ievent.reply('ERROR: %s' % str(ex))
        return
    if failed: ievent.reply('failed to delete %s' % ' '.join(failed))
    ievent.reply('%s item(s) removed' % itemsdeleted)

cmnds.add('lists-del', handle_listsdel, 'USER')
examples.add('lists-del', "lists-del <listname> ',' <listofnrs> .. remove items with indexnr from list", '1) lists-del 1 2) lists-del 0 3 6')

def handle_listshow(bot, ievent):
    """ show avaiable lists """
    username = users.getname(ievent.userhost)
    l = getlists(username)
    if not l: ievent.reply('no lists available') ; return
    else:
        result = []
        for i in l:
            if not i.listname in result:
                result.append(i.listname)
        ievent.reply("lists for %s: " % username, result)

cmnds.add('lists-show', handle_listshow, 'USER')
examples.add('lists-show', 'show available channel lists' , 'lists-show')

def handle_listsmerge(bot, ievent):
    """ merge 2 lists """
    try: (fromlist, tolist) = ievent.args
    except ValueError: ievent.missing('<fromlist> <tolist>') ; return
    username = users.getname(ievent.userhost)
    res = getlist(username, fromlist)
    if not res: ievent.reply('no %s list available or empty' % fromlist) ; return
    l = []
    for i in res: l.append(i.item)
    result = 0
    try: result = mergelist(username, tolist, l)
    except Exception, ex:
        handle_exception()
        ievent.reply('ERROR: %s' % str(ex))
        return
    ievent.reply('%s items merged' % result)

cmnds.add('lists-merge', handle_listsmerge, 'USER')
examples.add('lists-merge', 'lists-merge <fromlist> <tolist> .. merge 2 lists', 'lists-merge mekker miep')
